
#pragma once;

#include <iostream>

#include "os/os.h"

using namespace std;
using namespace os;

namespace{

    struct TestScanner:IScanner
    {
        TestScanner(SetPath& d, SetPath& f, const bool recursive = false)
            :mDirs(&d)
            ,mFiles(&f) 
            ,mInvalid(0) 
            ,mBegin(0) 
            ,mEnd(0) 
            ,mDirectory(0) 
            ,mFile(0) 
            ,mEnterDirectory(0) 
            ,mLeaveDirectory(0) 
            ,mTotal(0)
            ,mRecursive(recursive)
        {}

        virtual void Invalid(const fs::path&)   { ++mInvalid; ++mTotal; }
        virtual void Begin(const fs::path&)     { ++mBegin;   ++mTotal; }
        virtual void End(const fs::path&)       { ++mEnd;     ++mTotal; }
        
        virtual bool Directory(const fs::path& p)
        {
            ++mDirectory; ++mTotal; 
            mDirs->emplace(p);
            return mRecursive; 
        }
        virtual void File(const fs::path& p)
        {
            ++mFile; ++mTotal; 
            mFiles->emplace(p);
        }
        virtual void EnterDirectory(const fs::path&){ ++mEnterDirectory; ++mTotal; }
        virtual void LeaveDirectory(const fs::path&){ ++mLeaveDirectory; ++mTotal; }

        typedef const size_t Num;
        bool Check(Num i, Num b, Num e, Num d, Num f, Num ed, Num ld, Num t)const
        {
            return mInvalid == i && mBegin == b && mEnd == e && mDirectory == d && mFile == f &&
                mEnterDirectory == ed && mLeaveDirectory == ld &&  mTotal == t;
        }

        void Statictic()const
        {
            cout<< endl;
            cout<< "mInvalid        = " << mInvalid          << endl;
            cout<< "mBegin          = " << mBegin            << endl;
            cout<< "mEnd            = " << mEnd              << endl;
            cout<< "mDirectory      = " << mDirectory        << endl;
            cout<< "mFile           = " << mFile             << endl;
            cout<< "mEnterDirectory = " << mEnterDirectory   << endl;
            cout<< "mLeaveDirectory = " << mLeaveDirectory   << endl;
            cout<< "mTotal          = " << mTotal            << endl;
        }

        SetPath *mDirs, *mFiles;
        size_t mInvalid;
        size_t mBegin;
        size_t mEnd;
        size_t mDirectory;
        size_t mFile;
        size_t mEnterDirectory;
        size_t mLeaveDirectory;
        size_t mTotal;
        bool mRecursive;
    };

    struct ViewScanner: TestScanner
    {
        typedef TestScanner Parent;

        ViewScanner(SetPath& d, SetPath& f, const size_t deep, const bool recursive = false)
            :TestScanner(d,f,recursive) 
            ,mDeep(deep)
        {
            cout<<endl;
        }

        virtual void Invalid(const path& p)
        {
            cout << Deep(0) << "invalid : " << p <<endl; 
            Parent::Invalid(p);
        }

        virtual void Begin(const path& p)
        { 
            cout << Deep(0) << "begin : " << p.filename() << endl;
            Parent::Begin(p);
        }

        virtual void End(const path& p)      
        { 
            cout << Deep(0)<< "end : " << p.filename() << endl; 
            Parent::End(p);
        };

        virtual bool Directory(const path& p) 
        { 
            cout << Deep(4)<<"directory: " << p.filename() << endl; 
            return Parent::Directory(p);
        };

        virtual void File(const path& p)      
        { 
            cout << Deep(4) << "file : " << p.filename()<<endl; 
            Parent::File(p);
        };

        virtual void EnterDirectory(const path& p)
        {
            cout<<Deep(4)<<"enter : " << p.filename() << endl; ++mDeep; 
            Parent::EnterDirectory(p);
        };

        virtual void LeaveDirectory(const path& p)
        { 
            --mDeep; cout<<Deep(4)<<"leave : " << p.filename() << endl; 
            Parent::LeaveDirectory(p);
        };

        ::std::string Deep(const size_t n=0)const{ return ::std::string(mDeep*4+n, ' '); }

        size_t mDeep;
    };
   
}//namespace

